<template>
  <div class="scheduling-container">
    <!-- 搜索表单 -->
    <el-form :model="searchForm" ref="searchFormRef" :inline="true" class="search-form">
      <el-form-item label="产线名称" prop="productionLineName">
        <el-input v-model="searchForm.productionLineName" placeholder="请输入产线名称" clearable />
      </el-form-item>
      <el-form-item label="工单编号" prop="workOrderCode">
        <el-input v-model="searchForm.workOrderCode" placeholder="请输入工单编号" clearable />
      </el-form-item>
      <el-form-item label="产品名称" prop="productName">
        <el-input v-model="searchForm.productName" placeholder="请输入产品名称" clearable />
      </el-form-item>
      <el-form-item label="时间范围" prop="dateRange">
        <el-date-picker
          v-model="searchForm.dateRange"
          type="daterange"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          format="YYYY-MM-DD"
          value-format="YYYY-MM-DD"
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="handleSearch">查询</el-button>
        <el-button @click="handleReset">重置</el-button>
      </el-form-item>
    </el-form>

    <div class="table-header">
      <el-button type="success" :icon="Refresh" @click="handleAutoSchedule">自动排产</el-button>
      <el-button type="primary" @click="handleSaveAll" :disabled="modifiedWorkOrders.size === 0">
        保存所有更改 {{ modifiedWorkOrders.size > 0 ? `(${modifiedWorkOrders.size})` : '' }}
      </el-button>
      <el-button v-if="viewMode === 'gantt'" type="default" @click="scrollToToday">回到今天</el-button>
    </div>

    <!-- 甘特图视图 -->
    <div v-if="viewMode === 'gantt'" class="gantt-container" v-loading="loading">
      <!-- 时间轴头部 -->
      <div class="gantt-header">
        <div class="gantt-left-header">
          <div class="header-cell-container">
            <div class="header-cell merged-cell" style="width: 120px">产线编号</div>
            <div class="header-cell merged-cell" style="width: 150px">产线名称</div>
          </div>
        </div>
        <div class="gantt-right-header" ref="timeHeaderRef">
          <div class="time-header-content" :style="{ width: totalWidth + 'px' }">
            <!-- 年月行 -->
            <div class="time-scale year-month-row">
              <div v-for="month in monthScale" :key="month.key" class="time-cell month-cell" :style="{ width: month.width + 'px' }">
                {{ month.label }}
              </div>
            </div>
            <!-- 星期行 -->
            <div class="time-scale week-row">
              <div
                v-for="date in timeScale"
                :key="date.date + '-week'"
                class="time-cell week-cell"
                :style="{ width: cellWidth + 'px' }"
              >
                {{ date.weekLabel }}
              </div>
            </div>
            <!-- 日期行 -->
            <div class="time-scale date-row">
              <div
                v-for="date in timeScale"
                :key="date.date + '-date'"
                class="time-cell date-cell"
                :style="{ width: cellWidth + 'px' }"
              >
                {{ date.dateLabel }}
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 甘特图内容 -->
      <div class="gantt-content" ref="ganttContentRef">
        <div v-for="line in productionLines" :key="line.id" class="gantt-row">
          <!-- 左侧产线信息 -->
          <div class="gantt-left">
            <div class="line-cell" style="width: 120px">{{ line.lineCode }}</div>
            <div class="line-cell" style="width: 150px">{{ line.lineName }}</div>
          </div>

          <!-- 右侧甘特图区域 -->
          <div class="gantt-right">
            <div class="gantt-timeline" :style="{ width: totalWidth + 'px' }">
              <!-- 时间网格背景 -->
              <div class="time-grid">
                <div 
                  v-for="date in timeScale" 
                  :key="date.date" 
                  class="grid-cell" 
                  :class="{ 'today-cell': date.date === dayjs().format('YYYY-MM-DD') }"
                  :style="{ width: cellWidth + 'px' }"
                ></div>
              </div>

              <!-- 今天标记线 -->
              <div 
                v-if="getTodayPosition() >= 0" 
                class="today-line" 
                :style="{ left: getTodayPosition() + 'px' }"
              ></div>

              <!-- 工单条 -->
              <div
                v-for="workOrder in getWorkOrdersByLine(line.id)"
                :key="workOrder.id"
                class="work-order-bar"
                :class="{ 
                  selected: selectedWorkOrder?.id === workOrder.id,
                  dragging: dragState.isDragging && selectedWorkOrder?.id === workOrder.id,
                  resizing: dragState.isResizing && selectedWorkOrder?.id === workOrder.id
                }"
                :style="getWorkOrderStyle(workOrder)"
                @click="selectWorkOrder(workOrder)"
              >
                <!-- 左侧调整手柄 -->
                <div 
                  class="resize-handle left-handle" 
                  @mousedown.stop="startResize($event, workOrder, 'left')"
                  title="拖拽调整开始时间"
                ></div>

                <!-- 中间可拖拽区域 -->
                <div 
                  class="work-order-content"
                  @mousedown="startMove($event, workOrder)"
                  title="拖拽移动工单位置"
                >
                  <div class="work-order-title">{{ workOrder.workOrderCode }}</div>
                  <div class="work-order-subtitle">{{ workOrder.productName }}</div>
                </div>

                <!-- 右侧调整手柄 -->
                <div 
                  class="resize-handle right-handle" 
                  @mousedown.stop="startResize($event, workOrder, 'right')"
                  title="拖拽调整结束时间"
                ></div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

   
  </div>
</template>

<script setup lang="ts" name="productionLineScheduling">
import { ref, reactive, onMounted, onUnmounted, computed, watch } from "vue";
import type { FormInstance } from "element-plus";
import { ElMessage, ElMessageBox } from "element-plus";
import { EditPen, Refresh, View } from "@element-plus/icons-vue";
import dayjs from "dayjs";
import { getWorkOrderList, updateWorkOrder } from "@/api/modules/workorder";
import { getProductionLineList } from "@/api/modules/productionLine";
import type { WorkOrder } from "@/api/modules/workorder";
import type { ProductionLine } from "@/api/modules/productionLine";

const loading = ref(false);
const tableData = ref<any[]>([]);
const searchFormRef = ref<FormInstance>();
const formRef = ref<FormInstance>();
const timeHeaderRef = ref<HTMLElement>();
const ganttContentRef = ref<HTMLElement>();

// 视图模式
const viewMode = ref<"gantt" | "table">("gantt");

// 查询表单
const searchForm = reactive({
  productionLineName: "",
  workOrderCode: "",
  productName: "",
  dateRange: [] as string[]
});

// 产线数据
const productionLines = ref<ProductionLine.ProductionLineListItem[]>([]);

// 工单数据
const workOrders = ref<WorkOrder.WorkOrderListItem[]>([]);

// 记录已修改的工单
const modifiedWorkOrders = ref(new Set());

// 甘特图配置
const cellWidth = 80; // 每个时间单元格宽度

// 监听工单数据变化，自动滚动到合适位置
watch(workOrders, () => {
  if (workOrders.value.length > 0 && timeHeaderRef.value && ganttContentRef.value) {
    // 延迟执行，确保DOM已更新
    setTimeout(() => {
      scrollToToday();
    }, 100);
  }
}, { deep: true });

// 滚动到今天的位置
const scrollToToday = () => {
  const today = dayjs();
  const todayDiff = today.diff(startDate.value, "day", true);
  const scrollLeft = Math.max(0, todayDiff * cellWidth - 200); // 向左偏移200px以显示更多上下文
  
  if (timeHeaderRef.value) {
    timeHeaderRef.value.scrollLeft = scrollLeft;
  }
  if (ganttContentRef.value) {
    ganttContentRef.value.scrollLeft = scrollLeft;
  }
};

// 同步滚动
const syncScroll = (source: HTMLElement, target: HTMLElement) => {
  target.scrollLeft = source.scrollLeft;
};

// 获取今天的位置
const getTodayPosition = () => {
  const today = dayjs();
  const todayDiff = today.diff(startDate.value, "day", true);
  return todayDiff * cellWidth;
};

// 动态计算开始和结束时间
const startDate = computed(() => {
  if (workOrders.value.length === 0) {
    return dayjs().startOf("day");
  }
  
  // 找到所有工单中最早的开始时间
  const earliestStart = workOrders.value.reduce((earliest, workOrder) => {
    if (!workOrder.plannedStartTime) return earliest;
    
    const startTime = dayjs(workOrder.plannedStartTime);
    return !earliest || startTime.isBefore(earliest) ? startTime : earliest;
  }, null as dayjs.Dayjs | null);
  
  // 如果没有找到有效的开始时间，使用当前日期
  if (!earliestStart) {
    return dayjs().startOf("day");
  }
  
  // 向前扩展3天以提供缓冲区
  return earliestStart.subtract(3, "day").startOf("day");
});

const endDate = computed(() => {
  if (workOrders.value.length === 0) {
    return dayjs().add(30, "day").endOf("day");
  }
  
  // 找到所有工单中最晚的结束时间
  const latestEnd = workOrders.value.reduce((latest, workOrder) => {
    if (!workOrder.plannedEndTime) return latest;
    
    const endTime = dayjs(workOrder.plannedEndTime);
    return !latest || endTime.isAfter(latest) ? endTime : latest;
  }, null as dayjs.Dayjs | null);
  
  // 如果没有找到有效的结束时间，使用默认值
  if (!latestEnd) {
    return dayjs().add(30, "day").endOf("day");
  }
  
  // 向后扩展10天以提供缓冲区
  return latestEnd.add(10, "day").endOf("day");
});

// 时间刻度
const timeScale = computed(() => {
  const dates: Array<{
    date: string;
    label: string;
    weekLabel: string;
    dateLabel: string;
  }> = [];
  let current = startDate.value;

  while (current.isBefore(endDate.value) || current.isSame(endDate.value)) {
    const weekdays = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];

    dates.push({
      date: current.format("YYYY-MM-DD"),
      label: current.format("MM/DD"),
      weekLabel: weekdays[current.day()],
      dateLabel: current.format("M月D日")
    });
    current = current.add(1, "day");
  }

  return dates;
});

// 月份分组
const monthScale = computed(() => {
  const months: Array<{
    key: string;
    label: string;
    width: number;
  }> = [];

  let currentMonth = "";
  let dayCount = 0;

  timeScale.value.forEach((date, index) => {
    const monthKey = dayjs(date.date).format("YYYY-MM");

    if (monthKey !== currentMonth) {
      if (currentMonth && dayCount > 0) {
        months.push({
          key: currentMonth,
          label: dayjs(currentMonth).format("YYYY年MM月"),
          width: dayCount * cellWidth
        });
      }
      currentMonth = monthKey;
      dayCount = 1;
    } else {
      dayCount++;
    }

    // 处理最后一个月
    if (index === timeScale.value.length - 1) {
      months.push({
        key: currentMonth,
        label: dayjs(currentMonth).format("YYYY年MM月"),
        width: dayCount * cellWidth
      });
    }
  });

  return months;
});

// 甘特图总宽度
const totalWidth = computed(() => timeScale.value.length * cellWidth);

// 选中的工单
const selectedWorkOrder = ref<any>(null);

// 拖拽状态
const dragState = reactive({
  isDragging: false, // 整体移动
  isResizing: false, // 调整大小
  resizeType: "", // 'left' | 'right'
  startX: 0,
  startTime: "",
  endTime: "",
  animationId: null as number | null, // 用于取消 requestAnimationFrame
  currentRow: null as HTMLElement | null // 当前拖拽的行
});

// 弹窗相关
const dialogVisible = ref(false);
const dialogTitle = "编辑工单时间";

// 工单表单
const workOrderForm = reactive({
  id: "",
  workOrderCode: "",
  productName: "",
  productionLineId: "",
  plannedStartTime: "",
  plannedEndTime: "",
  plannedQuantity: 1
});

// 表单验证规则
const formRules = {
  plannedStartTime: [{ required: true, message: "请选择开始时间", trigger: "change" }],
  plannedEndTime: [{ required: true, message: "请选择结束时间", trigger: "change" }]
};

// 获取状态类型
const getStatusType = (status: string) => {
  const statusMap: Record<string, "warning" | "primary" | "success" | "info"> = {
    PENDING: "warning",
    SCHEDULED: "primary",
    PRODUCING: "success",
    COMPLETED: "info"
  };
  return statusMap[status] || "info";
};

// 获取状态文本
const getStatusText = (status: string) => {
  const statusMap: Record<string, string> = {
    PENDING: "待排产",
    SCHEDULED: "已排产",
    PRODUCING: "生产中",
    COMPLETED: "已完成"
  };
  return statusMap[status] || status;
};

// 根据产线ID获取工单
const getWorkOrdersByLine = (lineId: string) => {
  return workOrders.value.filter(wo => wo.productionLineId === lineId);
};

// 获取工单在甘特图中的样式
const getWorkOrderStyle = (workOrder: any) => {
  const startTime = dayjs(workOrder.plannedStartTime);
  const endTime = dayjs(workOrder.plannedEndTime);

  // 计算开始位置
  const startDiff = startTime.diff(startDate.value, "day", true);
  const left = Math.max(0, startDiff * cellWidth);

  // 计算宽度
  const duration = endTime.diff(startTime, "day", true);
  const width = Math.max(cellWidth * 0.8, duration * cellWidth);

  // 根据状态设置颜色
  const colorMap: Record<string, string> = {
    PENDING: "#f56c6c",
    SCHEDULED: "#409eff",
    PRODUCING: "#67c23a",
    COMPLETED: "#909399"
  };

  return {
    left: left + "px",
    width: width + "px",
    backgroundColor: colorMap[workOrder.status] || "#409eff"
  };
};

// 选择工单
const selectWorkOrder = (workOrder: any) => {
  selectedWorkOrder.value = workOrder;
};

// 检查鼠标是否在指定行内
const isMouseInRow = (event: MouseEvent, row: HTMLElement): boolean => {
  const rect = row.getBoundingClientRect();
  return event.clientY >= rect.top && event.clientY <= rect.bottom;
};

// 开始移动工单（整体平移）
const startMove = (event: MouseEvent, workOrder: any) => {
  if (dragState.isResizing) return;

  event.preventDefault();
  event.stopPropagation();
  
  dragState.isDragging = true;
  dragState.startX = event.clientX;
  dragState.startTime = workOrder.plannedStartTime;
  dragState.endTime = workOrder.plannedEndTime;
  selectedWorkOrder.value = workOrder;

  // 找到当前工单所在的行
  const workOrderElement = event.target as HTMLElement;
  const ganttRow = workOrderElement.closest('.gantt-row') as HTMLElement;
  dragState.currentRow = ganttRow;

  // 添加移动样式
  document.body.style.cursor = 'grabbing';
  document.body.style.userSelect = 'none';

  // 高亮当前行
  if (ganttRow) {
    ganttRow.classList.add('dragging-row');
  }

  document.addEventListener("mousemove", handleMove, { passive: false });
  document.addEventListener("mouseup", stopDrag);
  
  // 当鼠标离开当前行时停止拖拽
  if (ganttRow) {
    ganttRow.addEventListener("mouseleave", stopDrag, { once: true });
  }
  
  // 添加额外的全局检查，防止意外情况
  document.addEventListener("mouseleave", stopDrag, { once: true });
};

// 处理工单移动（整体平移，保持工期不变）
const handleMove = (event: MouseEvent) => {
  if (!dragState.isDragging || !selectedWorkOrder.value || !dragState.currentRow) return;

  event.preventDefault();
  
  // 检查鼠标是否还在当前行内
  if (!isMouseInRow(event, dragState.currentRow)) {
    stopDrag();
    return;
  }
  
  const deltaX = event.clientX - dragState.startX;
  
  // 取消之前的动画帧
  if (dragState.animationId) {
    cancelAnimationFrame(dragState.animationId);
  }
  
  // 使用 requestAnimationFrame 优化性能
  dragState.animationId = requestAnimationFrame(() => {
    // 再次检查拖拽状态，确保没有被停止
    if (!dragState.isDragging || !selectedWorkOrder.value) {
      dragState.animationId = null;
      return;
    }
    
    const deltaDays = deltaX / cellWidth;
    
    // 添加网格吸附功能，让拖拽更精确
    const snappedDeltaDays = Math.round(deltaDays * 4) / 4; // 按四分之一天吸附
    
    const originalStart = dayjs(dragState.startTime);
    const originalEnd = dayjs(dragState.endTime);
    const duration = originalEnd.diff(originalStart, "day", true);

    // 整体移动：开始和结束时间都按相同的偏移量移动
    const newStart = originalStart.add(snappedDeltaDays, "day");
    const newEnd = newStart.add(duration, "day");

    selectedWorkOrder.value.plannedStartTime = newStart.format("YYYY-MM-DD HH:mm:ss");
    selectedWorkOrder.value.plannedEndTime = newEnd.format("YYYY-MM-DD HH:mm:ss");
    
    dragState.animationId = null;
  });
};

// 停止拖拽
const stopDrag = () => {
  // 取消任何正在进行的动画帧
  if (dragState.animationId) {
    cancelAnimationFrame(dragState.animationId);
    dragState.animationId = null;
  }

  if (dragState.isDragging || dragState.isResizing) {
    // 标记为已修改
    if (selectedWorkOrder.value) {
      modifiedWorkOrders.add(selectedWorkOrder.value.id);
    }
  }

  // 恢复样式
  document.body.style.cursor = '';
  document.body.style.userSelect = '';

  // 移除行高亮
  if (dragState.currentRow) {
    dragState.currentRow.classList.remove('dragging-row', 'resizing-row');
  }

  // 重置拖拽状态
  dragState.isDragging = false;
  dragState.isResizing = false;
  dragState.resizeType = "";
  dragState.currentRow = null;
  
  // 移除所有事件监听器
  document.removeEventListener("mousemove", handleMove);
  document.removeEventListener("mousemove", handleResize);
  document.removeEventListener("mouseup", stopDrag);
  
  // 移除所有行级别的 mouseleave 监听器（由于使用了 once: true，通常已经自动移除）
  document.querySelectorAll('.gantt-row').forEach(row => {
    row.removeEventListener("mouseleave", stopDrag);
  });
};

// 开始调整大小
const startResize = (event: MouseEvent, workOrder: any, type: "left" | "right") => {
  event.stopPropagation();
  event.preventDefault();

  dragState.isResizing = true;
  dragState.resizeType = type;
  dragState.startX = event.clientX;
  dragState.startTime = workOrder.plannedStartTime;
  dragState.endTime = workOrder.plannedEndTime;
  selectedWorkOrder.value = workOrder;

  // 找到当前工单所在的行
  const resizeElement = event.target as HTMLElement;
  const ganttRow = resizeElement.closest('.gantt-row') as HTMLElement;
  dragState.currentRow = ganttRow;

  // 设置调整大小的鼠标样式
  document.body.style.cursor = 'ew-resize';
  document.body.style.userSelect = 'none';

  // 高亮当前行
  if (ganttRow) {
    ganttRow.classList.add('resizing-row');
  }

  document.addEventListener("mousemove", handleResize, { passive: false });
  document.addEventListener("mouseup", stopDrag);
  
  // 当鼠标离开当前行时停止调整大小
  if (ganttRow) {
    ganttRow.addEventListener("mouseleave", stopDrag, { once: true });
  }
  
  // 添加额外的全局检查，防止意外情况
  document.addEventListener("mouseleave", stopDrag, { once: true });
};

// 处理调整大小
const handleResize = (event: MouseEvent) => {
  if (!dragState.isResizing || !selectedWorkOrder.value || !dragState.currentRow) return;

  event.preventDefault();
  
  // 检查鼠标是否还在当前行内
  if (!isMouseInRow(event, dragState.currentRow)) {
    stopDrag();
    return;
  }
  
  const deltaX = event.clientX - dragState.startX;
  
  // 取消之前的动画帧
  if (dragState.animationId) {
    cancelAnimationFrame(dragState.animationId);
  }
  
  // 使用 requestAnimationFrame 优化性能
  dragState.animationId = requestAnimationFrame(() => {
    // 再次检查拖拽状态，确保没有被停止
    if (!dragState.isResizing || !selectedWorkOrder.value) {
      dragState.animationId = null;
      return;
    }
    
    const deltaDays = deltaX / cellWidth;
    
    // 添加网格吸附功能
    const snappedDeltaDays = Math.round(deltaDays * 4) / 4; // 按四分之一天吸附

    if (dragState.resizeType === "left") {
      const newStart = dayjs(dragState.startTime).add(snappedDeltaDays, "day");
      const endTime = dayjs(dragState.endTime);

      // 确保开始时间不晚于结束时间，至少保持1小时的最小工期
      if (newStart.isBefore(endTime.subtract(1, "hour"))) {
        selectedWorkOrder.value.plannedStartTime = newStart.format("YYYY-MM-DD HH:mm:ss");
      }
    } else if (dragState.resizeType === "right") {
      const newEnd = dayjs(dragState.endTime).add(snappedDeltaDays, "day");
      const startTime = dayjs(dragState.startTime);

      // 确保结束时间不早于开始时间，至少保持1小时的最小工期
      if (newEnd.isAfter(startTime.add(1, "hour"))) {
        selectedWorkOrder.value.plannedEndTime = newEnd.format("YYYY-MM-DD HH:mm:ss");
      }
    }
    
    dragState.animationId = null;
  });
};

// 保存所有更改
const handleSaveAll = async () => {
  if (modifiedWorkOrders.size === 0) {
    ElMessage.info("没有需要保存的更改");
    return;
  }

  try {
    const modifiedCount = modifiedWorkOrders.size;

    // 批量保存修改的工单
    const savePromises = Array.from(modifiedWorkOrders).map(async workOrderId => {
      const workOrder = workOrders.value.find(wo => wo.id === workOrderId);
      if (workOrder) {
        const updateParams: WorkOrder.CreateWorkOrderRequest = {
          workOrderCode: workOrder.workOrderCode,
          productId: workOrder.productId || "",
          plannedQuantity: workOrder.plannedQuantity,
          routeId: workOrder.routeId,
          productionLineId: workOrder.productionLineId,
          workOrderType: workOrder.workOrderType || "PRODUCTION",
          plannedStartTime: workOrder.plannedStartTime as string,
          plannedEndTime: workOrder.plannedEndTime as string,
          remarks: workOrder.remarks
        };

        await updateWorkOrder(workOrder.id, updateParams);
      }
    });

    await Promise.all(savePromises);

    modifiedWorkOrders.clear();
    ElMessage.success(`成功保存 ${modifiedCount} 个工单的时间调整`);
  } catch (error) {
    console.error("保存失败:", error);
    ElMessage.error("保存失败");
  }
};


// 获取产线数据
const getProductionLines = async () => {
  try {
    const { data } = await getProductionLineList({ size: 1000 });
    productionLines.value = data.records || [];
  } catch (error) {
    console.error("获取产线数据失败:", error);
    ElMessage.error("获取产线数据失败");
  }
};

// 获取工单数据
const getWorkOrders = async () => {
  try {
    const params: WorkOrder.WorkOrderListParams = {
      size: 1000
    };

    // 添加搜索条件
    if (searchForm.workOrderCode) {
      params.workOrderCode = searchForm.workOrderCode;
    }
    if (searchForm.productName) {
      params.productCode = searchForm.productName;
    }

    const { data } = await getWorkOrderList(params);
    workOrders.value = data.records || [];
  } catch (error) {
    console.error("获取工单数据失败:", error);
    ElMessage.error("获取工单数据失败");
  }
};

// 获取表格数据
const getTableData = async () => {
  loading.value = true;
  try {
    await Promise.all([getProductionLines(), getWorkOrders()]);

    // 转换工单数据为表格格式
    tableData.value = workOrders.value.map(wo => ({
      ...wo,
      productionLineName: productionLines.value.find(line => line.id === wo.productionLineId)?.lineName || ""
    }));
  } catch (error) {
    console.error("获取数据失败:", error);
    ElMessage.error("获取数据失败");
  } finally {
    loading.value = false;
  }
};

// 获取甘特图数据
const getGanttData = async () => {
  loading.value = true;
  try {
    await Promise.all([getProductionLines(), getWorkOrders()]);
    
    // 数据加载完成后，滚动到合适位置
    setTimeout(() => {
      scrollToToday();
    }, 200);
  } catch (error) {
    console.error("获取甘特图数据失败:", error);
    ElMessage.error("获取甘特图数据失败");
  } finally {
    loading.value = false;
  }
};

// 查询
const handleSearch = () => {
  if (viewMode.value === "table") {
    getTableData();
  } else {
    getGanttData();
  }
};

// 重置
const handleReset = () => {
  if (!searchFormRef.value) return;
  searchFormRef.value.resetFields();
  if (viewMode.value === "table") {
    getTableData();
  } else {
    getGanttData();
  }
};

// 自动排产
const handleAutoSchedule = () => {
  ElMessage.info("自动排产功能待实现");
};

// 编辑工单时间
const handleEdit = (row: any) => {
  Object.assign(workOrderForm, {
    id: row.id,
    workOrderCode: row.workOrderCode,
    productName: row.productName,
    productionLineId: row.productionLineId,
    plannedStartTime: row.plannedStartTime,
    plannedEndTime: row.plannedEndTime,
    plannedQuantity: row.plannedQuantity
  });
  dialogVisible.value = true;
};

// 关闭弹窗
const handleDialogClose = () => {
  if (formRef.value) {
    formRef.value.clearValidate();
  }
};

// 提交表单
const handleSubmit = () => {
  if (!formRef.value) return;

  formRef.value.validate(valid => {
    if (valid) {
      // 更新工单时间
      const index = workOrders.value.findIndex(wo => wo.id === workOrderForm.id);
      if (index > -1) {
        workOrders.value[index].plannedStartTime = workOrderForm.plannedStartTime;
        workOrders.value[index].plannedEndTime = workOrderForm.plannedEndTime;

        // 标记为已修改
        modifiedWorkOrders.add(workOrderForm.id);

        ElMessage.success("时间调整成功");
      }

      dialogVisible.value = false;
      if (viewMode.value === "table") {
        getTableData();
      }
    }
  });
};

// 页面加载时获取数据
onMounted(() => {
  if (viewMode.value === "table") {
    getTableData();
  } else {
    getGanttData();
  }

  // 添加滚动同步事件监听
  setTimeout(() => {
    if (timeHeaderRef.value && ganttContentRef.value) {
      timeHeaderRef.value.addEventListener('scroll', () => {
        syncScroll(timeHeaderRef.value!, ganttContentRef.value!);
      });
      
      ganttContentRef.value.addEventListener('scroll', () => {
        syncScroll(ganttContentRef.value!, timeHeaderRef.value!);
      });
    }
  }, 500);
});

// 组件卸载时清理
onUnmounted(() => {
  // 取消任何正在进行的动画帧
  if (dragState.animationId) {
    cancelAnimationFrame(dragState.animationId);
  }
  
  // 移除所有可能的事件监听器
  document.removeEventListener("mousemove", handleMove);
  document.removeEventListener("mousemove", handleResize);
  document.removeEventListener("mouseup", stopDrag);
  
  // 移除所有行级别的事件监听器
  document.querySelectorAll('.gantt-row').forEach(row => {
    row.removeEventListener("mouseleave", stopDrag);
  });
  
  // 恢复样式
  document.body.style.cursor = '';
  document.body.style.userSelect = '';
});
</script>

<style scoped>
.scheduling-container {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.search-form {
  background-color: #fff;
  padding: 20px;
  border-radius: 4px;
  margin-bottom: 16px;
  flex-shrink: 0;
}

.table-header {
  margin-bottom: 16px;
  display: flex;
  gap: 10px;
  flex-shrink: 0;
}

/* 甘特图样式 */
.gantt-container {
  flex: 1;
  background: #fff;
  border-radius: 4px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  position: relative;
}

.gantt-header {
  display: flex;
  border-bottom: 2px solid #e4e7ed;
  background: #f5f7fa;
  flex-shrink: 0;
}

.gantt-left-header {
  display: flex;
  border-right: 2px solid #e4e7ed;
  flex-shrink: 0;
  height: 96px; /* 3行 * 32px */
}

.header-cell-container {
  display: flex;
  width: 100%;
}

.merged-cell {
  height: 96px !important; /* 跨越三行 */
}

.gantt-right-header {
  flex: 1;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
  scrollbar-color: #c1c1c1 transparent;
}

.gantt-right-header::-webkit-scrollbar {
  height: 8px;
}

.gantt-right-header::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 4px;
}

.gantt-right-header::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 4px;
}

.gantt-right-header::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

.time-header-content {
  display: flex;
  flex-direction: column;
}

.header-cell {
  padding: 8px;
  border-right: 1px solid #e4e7ed;
  border-bottom: 1px solid #e4e7ed;
  font-weight: 600;
  text-align: center;
  background: #f5f7fa;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 32px;
}

.time-scale {
  display: flex;
  height: 32px;
}

.year-month-row {
  border-bottom: 1px solid #e4e7ed;
}

.week-row {
  border-bottom: 1px solid #e4e7ed;
}

.date-row {
  /* 最后一行不需要下边框 */
}

.time-cell {
  border-right: 1px solid #e4e7ed;
  padding: 4px 2px;
  text-align: center;
  background: #f5f7fa;
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  font-size: 12px;
  height: 32px;
}

.month-cell {
  font-weight: 600;
  background: #eef1f6;
  font-size: 13px;
}

.week-cell {
  font-weight: 500;
  color: #606266;
  font-size: 11px;
}

.date-cell {
  font-weight: 400;
  color: #303133;
  font-size: 12px;
}

.gantt-content {
  flex: 1;
  overflow-y: auto;
  overflow-x: auto;
  scrollbar-width: thin;
  scrollbar-color: #c1c1c1 transparent;
}

.gantt-content::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

.gantt-content::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 4px;
}

.gantt-content::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 4px;
}

.gantt-content::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

.gantt-content::-webkit-scrollbar-corner {
  background: #f1f1f1;
}

.gantt-row {
  display: flex;
  border-bottom: 1px solid #e4e7ed;
  min-height: 60px;
  transition: background-color 0.15s ease;
}

.gantt-row:hover {
  background-color: rgba(64, 158, 255, 0.02);
}

.gantt-row.dragging-row {
  background-color: rgba(64, 158, 255, 0.08);
  border-top: 2px solid rgba(64, 158, 255, 0.3);
  border-bottom: 2px solid rgba(64, 158, 255, 0.3);
}

.gantt-row.resizing-row {
  background-color: rgba(64, 158, 255, 0.05);
  border-top: 1px solid rgba(64, 158, 255, 0.2);
  border-bottom: 1px solid rgba(64, 158, 255, 0.2);
}

.gantt-left {
  display: flex;
  border-right: 2px solid #e4e7ed;
  flex-shrink: 0;
  background: #fff;
}

.line-cell {
  padding: 12px 8px;
  border-right: 1px solid #e4e7ed;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fff;
}

.gantt-right {
  flex: 1;
  min-height: 60px;
  overflow: hidden;
}

.gantt-timeline {
  position: relative;
  min-height: 60px;
}

.time-grid {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
}

.grid-cell {
  border-right: 1px solid #e4e7ed;
  height: 100%;
}

.today-cell {
  background-color: rgba(64, 158, 255, 0.1);
}

.today-line {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 2px;
  background-color: #409eff;
  z-index: 10;
  pointer-events: none;
}

.today-line::before {
  content: '';
  position: absolute;
  top: -4px;
  left: -4px;
  width: 10px;
  height: 10px;
  background-color: #409eff;
  border-radius: 50%;
}

.work-order-bar {
  position: absolute;
  top: 8px;
  height: 44px;
  border-radius: 4px;
  cursor: default;
  display: flex;
  align-items: center;
  padding: 0;
  color: white;
  font-size: 12px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
  user-select: none;
  will-change: transform, box-shadow;
  overflow: hidden;
}

.work-order-bar:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
  transform: translateY(-1px);
}

.work-order-bar.selected {
  box-shadow: 0 0 0 2px #409eff, 0 4px 12px rgba(64, 158, 255, 0.3);
}

.work-order-bar.dragging {
  cursor: grabbing;
  transform: scale(1.02);
  z-index: 1000;
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
  opacity: 0.9;
  transition: none;
}

.work-order-bar.resizing {
  z-index: 1000;
  box-shadow: 0 4px 15px rgba(64, 158, 255, 0.4);
  transition: none;
}

.work-order-bar.resizing .resize-handle {
  opacity: 1;
  background: rgba(64, 158, 255, 0.8);
}

.work-order-bar.resizing .work-order-content {
  pointer-events: none;
}

.work-order-content {
  flex: 1;
  overflow: hidden;
  cursor: grab;
  padding: 4px 8px;
  border-radius: 2px;
  transition: background-color 0.15s ease;
}

.work-order-content:hover {
  background-color: rgba(255, 255, 255, 0.1);
}

.work-order-content:active {
  cursor: grabbing;
}

.work-order-title {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.work-order-subtitle {
  font-size: 11px;
  opacity: 0.9;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.resize-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 8px;
  cursor: ew-resize;
  background: rgba(255, 255, 255, 0.4);
  opacity: 0;
  transition: all 0.15s ease;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
}

.resize-handle::before {
  content: '';
  width: 2px;
  height: 60%;
  background: rgba(255, 255, 255, 0.8);
  border-radius: 1px;
}

.work-order-bar:hover .resize-handle {
  opacity: 1;
}

.work-order-bar.selected .resize-handle {
  opacity: 1;
  background: rgba(255, 255, 255, 0.6);
}

.left-handle {
  left: 0;
  border-radius: 4px 0 0 4px;
}

.right-handle {
  right: 0;
  border-radius: 0 4px 4px 0;
}

.resize-handle:hover {
  background: rgba(255, 255, 255, 0.8);
  width: 10px;
}

.resize-handle:hover::before {
  background: rgba(255, 255, 255, 1);
  width: 3px;
}

.resize-handle:active {
  background: rgba(255, 255, 255, 0.9);
}

/* 弹窗样式 */
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

/* 响应式 */
@media (max-width: 768px) {
  .gantt-left-header,
  .gantt-left {
    display: none;
  }

  .work-order-bar {
    font-size: 11px;
    padding: 0 4px;
  }

  .time-cell {
    padding: 8px 4px;
    font-size: 12px;
  }
}
</style>